基础
在 Vue 中子组件为何不可以修改父组件传递的 Prop,如果修改了,Vue 是如何监控到属性的修改并给出警告的
子组件为何不可以修改父组件传递的 Prop 单向数据流,易于监测数据的流动,出现了错误可以更加迅速的定位到错误发生的位置。 如果修改了,Vue 是如何监控到属性的修改并给出警告的。
if (process.env.NODE_ENV !== "production") {
var hyphenatedKey = hyphenate(key);
if (
isReservedAttribute(hyphenatedKey) ||
config.isReservedAttr(hyphenatedKey)
) {
warn(
'"' +
hyphenatedKey +
'" is a reserved attribute and cannot be used as component prop.',
vm
);
}
defineReactive$$1(props, key, value, function () {
if (!isRoot && !isUpdatingChildComponent) {
warn(
"Avoid mutating a prop directly since the value will be " +
"overwritten whenever the parent component re-renders. " +
"Instead, use a data or computed property based on the prop's " +
'value. Prop being mutated: "' +
key +
'"',
vm
);
}
});
}
在 initProps 的时候,在 defineReactive 时通过判断是否在开发环境,如果是开发环境,会在触发 set 的时候判断是否此 key 是否处于 updatingChildren 中被修改,如果不是,说明此修改来自子组件,触发 warning 提示。
需要特别注意的是,当你从子组件修改的 prop 属于基础类型时会触发提示。 这种情况下,你是无法修改父组件的数据源的, 因为基础类型赋值时是值拷贝。你直接将另一个非基础类型(Object, array)赋值到此 key 时也会触发提示(但实际上不会影响父组件的数据源), 当你修改 object 的属性时不会触发提示,并且会修改父组件数据源的数据。
组件通信
组件通信一般分为以下几种情况:
- 父子组件通信
- 兄弟组件通信
- 跨多层级组件通信
- 任意组件
兄弟组件通信
通过 this.$parent.$children,在 $children 中可以通过组件 name 查询到需要的组件实例,然后进行通信。
父子组件通信
- emit/props
$parent.xxx- provide/injected 跨多层次组件通信
- event bus
- Vuex
$listeners和.sync
任意组件
- event bus
- Vuex
Vue JSX
JSX 中指令是否还可用?
大多数指令并不能在 JSX 中使用,对于原生指令,只有 v-show 是支持的。但是大部分指令在 JSX 中可以使用表达式来替代,如:条件运算符(?:)替代 v-if、array.map 替代 v-for
对于自定义的指令,可以使用如下方式使用:
const directives = [{ name: "my-dir", value: 123, modifiers: { abc: true } }];
return <div {...{ directives }} />;
使用 jsx 的优劣
好处:
- 更加灵活的表达
- 自定义的渲染函数,ant d 中的 table , customRender 之类的渲染函数,能够更加自由的填充开发者想填写的内容
- html 模板与数据处于一个地方,单文件组件 template 的需要上下移动
- 与 TS 结合比较好, template 模板部分 vue 2.0 暂时不能很好支持
- 不是很确定:通常情况下, spa 不会去线上编译模板代码,所以只是开发阶段的编译速度会增加,因为 template 会被编译成 render 函数,tsx/jsx 讲道理好像没有这个过程,html 标签会直接通过 h 函数被编译成 vnode
- 对于需要做两个技术栈的开发者来说 是好事。
坏处:
- render 函数的写法需要有一定的基础
- 与 TS 结合之后,mixins 的写法有一定的误解性, 因为需要类型推导,所以 只能通过 Vue.extend 来实现一个 mixins ,每一个 mixins 需要写成一个 vue 类,而不是 options 的一部分,一个简单的对象即可
其他东西都没有变化,只是 template 变成了 jsx 的形式。template 本来就会被转化成一个 render 函数,现在构建时减少了一次编译。
优点:
- 更加灵活。
- 编译更快。
- 对于 vue2 来说是有更好的类型支持,毕竟 template 中类型支持不是很好。
缺点:
- 与 vue 最推崇的方式有差别,有些人不喜欢 jsx 的写法,不习惯的人写起来会比较难受。
- template 模式 vue 会在编译时做很多静态优化,现在 render 函数直接是用户提供,缺少了原生的这些优化。
- 无法使用指令